home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / sys / mac / macfile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  10.5 KB  |  497 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)macfile.c    3.1    93/01/24          */
  2. /* Copyright (c) Jon W{tte, Hao-Yang Wang, Jonathan Handler 1992. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4. /*
  5.  * macfile.c
  6.  * MAC file I/O routines
  7.  */
  8.  
  9. #include "hack.h"
  10.  
  11. #include <files.h>
  12. #include <errors.h>
  13. #include <resources.h>
  14. #include <memory.h>
  15. #include <ToolUtils.h>
  16.  
  17. /*
  18.  * We should get the default dirID and volRefNum (from name) from prefs and
  19.  * the situation at startup... For now, this will have to do.
  20.  */
  21.  
  22.  
  23. /* The HandleFiles are resources built into the application which are treated
  24.    as read-only files: if we fail to open a file we look for a resource */
  25.    
  26. #define FIRST_HF 32000   /* file ID of first HandleFile */
  27. #define MAX_HF 6         /* Max # of open HandleFiles */
  28.  
  29. #define APP_NAME_RES_ID        (-16396)
  30. #define PLAYER_NAME_RES_ID    1001
  31.  
  32. int FDECL(maccreat,(const char *, long));
  33. int FDECL(macopen,(const char *, int, long));
  34. int FDECL(macclose,(int));
  35. int FDECL(macread,(int, void *, unsigned));
  36. int FDECL(macwrite,(int, void *, unsigned));
  37. long FDECL(macseek,(int, long, short));
  38.  
  39. char * FDECL(macgets,(int, char *, unsigned));
  40.  
  41. static short FDECL(IsHandleFile,(int));
  42. static int FDECL(OpenHandleFile,(const unsigned char *, long));
  43. static int FDECL(CloseHandleFile,(int));
  44. static int FDECL(ReadHandleFile,(int, void *, unsigned));
  45. static long FDECL(SetHandleFilePos,(int, short, long));
  46. static void FDECL(C2P,(const char *, unsigned char *));
  47.  
  48. typedef struct handlefile {
  49.     long        type ;  /* Resource type */
  50.     short        id ;    /* Resource id */
  51.     long        mark ;  /* Current position */
  52.     long        size ;  /* total size */
  53.     Handle        data ;  /* The resource, purgeable */
  54. } HandleFile ;
  55.  
  56. HandleFile theHandleFiles [ MAX_HF ] ;
  57.  
  58. static short
  59. IsHandleFile ( int fd )
  60. {
  61.     return (fd >= FIRST_HF) && 
  62.            (fd < FIRST_HF + MAX_HF) && 
  63.            (theHandleFiles[ fd - FIRST_HF ].data) ;
  64. }
  65.  
  66.  
  67. static int
  68. OpenHandleFile ( const unsigned char * name , long fileType )
  69. {
  70.     int i ;
  71.     OSErr err;
  72.     Handle h ;
  73.     Str255 s ;
  74.  
  75.     for ( i = 0 ; i < MAX_HF ; i ++ ) {
  76.         if ( theHandleFiles[i].data == 0L ) break ;
  77.     }
  78.     
  79.     if ( i >= MAX_HF ) {
  80.         error("Ran out of HandleFiles");
  81.         return -1 ;
  82.     }
  83.  
  84.     h = GetNamedResource ( fileType , name ) ;
  85.     err = ResError();
  86.     if (err == resNotFound) return -1;  /* Don't complain, this might be normal */
  87.     if ( ! itworked(err) ) return -1;
  88.     
  89.     theHandleFiles[i].data = h;
  90.     theHandleFiles[i].size = GetHandleSize ( h ) ;
  91.     GetResInfo ( h, & theHandleFiles[i].id, ( void* ) & theHandleFiles[i].type, s ) ;
  92.     theHandleFiles[i].mark = 0L ;
  93.  
  94.     HPurge( h ) ;
  95.     return(i + FIRST_HF);
  96. }
  97.  
  98.  
  99. static int
  100. CloseHandleFile ( int fd )
  101. {
  102.     if ( ! IsHandleFile ( fd ) ) {
  103.        error("CloseHandleFile: isn't a handle");
  104.        return -1 ;
  105.     }
  106.     fd -= FIRST_HF ;
  107.     ReleaseResource ( theHandleFiles[fd].data ) ;
  108.     theHandleFiles[fd].data = 0L ;
  109.     return(0);
  110. }
  111.  
  112.  
  113. static int
  114. ReadHandleFile ( int fd , void * ptr , unsigned len )
  115. {
  116.     unsigned maxBytes ;
  117.     Handle h ;
  118.  
  119.     if ( ! IsHandleFile ( fd ) ) return -1;
  120.     
  121.     fd -= FIRST_HF ;
  122.     maxBytes = theHandleFiles[fd].size - theHandleFiles[fd].mark ;
  123.     if ( len > maxBytes ) len = maxBytes ;
  124.     
  125.     h = theHandleFiles[fd].data ;
  126.     LoadResource ( h ) ;
  127.     if ( ! itworked(ResError()) ) return (-1);
  128.     
  129.     HLock(h);
  130.     BlockMove ( *h + theHandleFiles[fd].mark , ptr , len );
  131.     HUnlock(h);
  132.     theHandleFiles[fd].mark += len ;
  133.  
  134. /*    comment("ReadHandleFile ",len); */
  135.     
  136.     return(len);
  137. }
  138.  
  139.  
  140. static long
  141. SetHandleFilePos ( int fd , short whence , long pos )
  142. {
  143.     long curpos;
  144.     
  145.     if ( ! IsHandleFile ( fd ) ) return -1;
  146.     
  147.     fd -= FIRST_HF ;
  148.     
  149.     curpos = theHandleFiles [ fd ].mark;
  150.     switch ( whence ) {
  151.     case SEEK_CUR : 
  152.         curpos += pos ;
  153.         break ;
  154.     case SEEK_END : 
  155.         curpos = theHandleFiles[fd].size  - pos ;
  156.         break ;
  157.     default : /* set */
  158.         curpos = pos ;
  159.         break ;
  160.     }
  161.  
  162.     if ( curpos < 0 ) curpos = 0 ;
  163.     
  164.     if ( curpos > theHandleFiles [ fd ].size ) curpos = theHandleFiles [ fd ].size ;
  165.     
  166.     theHandleFiles [ fd ].mark = curpos;
  167.     
  168.     return curpos ;
  169. }
  170.  
  171.  
  172. static void
  173. C2P ( const char * c , unsigned char * p )
  174. {
  175.     long len = strlen ( c ) ;
  176.  
  177.     if ( len > 255 ) len = 255 ;
  178.  
  179.     p[0] = len & 0xff ;
  180.     while (*c) *++p = *c++;
  181. }
  182.  
  183. static void
  184. P2C ( const unsigned char * p , char * c )
  185. {
  186.     int idx = p[0];
  187.     c[idx] = '\0';
  188.     while (idx > 0) {
  189.         c[idx-1] = p[idx];
  190.         --idx;
  191.     }
  192. }
  193.  
  194.  
  195. static void
  196. replace_resource(Handle new_res, ResType its_type, short its_id,
  197.                  Str255 its_name) {
  198.     Handle old_res;
  199.     SetResLoad(false);
  200.     old_res = Get1Resource(its_type, its_id);
  201.     SetResLoad(true);
  202.     if (old_res) {
  203.         RmveResource(old_res);
  204.         DisposHandle(old_res);
  205.     }
  206.  
  207.     AddResource(new_res, its_type, its_id, its_name);
  208. }
  209.  
  210.  
  211. int
  212. maccreat ( const char * name , long fileType )
  213. {
  214.     return macopen ( name , O_RDWR | O_CREAT | O_TRUNC , fileType ) ;
  215. }
  216.  
  217.  
  218. int
  219. macopen ( const char * name , int flags , long fileType )
  220. {
  221.     short refNum ;
  222.     short perm ;
  223.     Str255 s ;
  224.  
  225.     C2P ( name , s ) ;
  226.     if ( flags & O_CREAT ) {
  227.         if ( HCreate ( theDirs.dataRefNum , theDirs.dataDirID , s ,
  228.             MAC_CREATOR , fileType ) && ( flags & O_EXCL ) ) {
  229.             return -1 ;
  230.         }
  231.  
  232.         if (fileType == SAVE_TYPE) {
  233.             short resRef;
  234.             HCreateResFile(theDirs.dataRefNum, theDirs.dataDirID, s);
  235.             resRef = HOpenResFile(theDirs.dataRefNum, theDirs.dataDirID, s,
  236.                                   fsRdWrPerm);
  237.             if (resRef != -1) {
  238.                 Handle name;
  239.                 Str255 plnamep;
  240.  
  241.                 C2P(plname, plnamep);
  242.                 name = (Handle)NewString(plnamep);
  243.                 if (name)
  244.                     replace_resource(name, 'STR ', PLAYER_NAME_RES_ID,
  245.                                     "\pPlayer Name");
  246.  
  247.                 /* The application name resource.  See IM VI, page 9-21. */
  248.                 name = (Handle)GetString(APP_NAME_RES_ID);
  249.                 if (name) {
  250.                     DetachResource(name);
  251.                     replace_resource(name, 'STR ', APP_NAME_RES_ID,
  252.                                      "\pApplication Name");
  253.                 }
  254.  
  255.                 CloseResFile(resRef);
  256.             }
  257.         }
  258.  
  259.     }
  260.     /*
  261.      * Here, we should check for file type, maybe a SFdialog if
  262.      * we fail with default, etc. etc. Besides, we should use HOpen
  263.      * and permissions.
  264.      */
  265.     if ( ( flags & O_RDONLY ) == O_RDONLY ) {
  266.         perm = fsRdPerm ;
  267.     }
  268.     if ( ( flags & O_WRONLY ) == O_WRONLY ) {
  269.         perm = fsWrPerm ;
  270.     }
  271.     if ( ( flags & O_RDWR ) == O_RDWR ) {
  272.         perm = fsRdWrPerm ;
  273.     }
  274.     if ( HOpen ( theDirs.dataRefNum , theDirs.dataDirID , s ,
  275.         perm , & refNum ) ) {
  276.         return OpenHandleFile ( s , fileType ) ;
  277.     }
  278.     if ( flags & O_TRUNC ) {
  279.         if ( SetEOF ( refNum , 0L ) ) {
  280.             FSClose ( refNum ) ;
  281.             return -1 ;
  282.         }
  283.     }
  284.     return refNum ;
  285. }
  286.  
  287.  
  288. int
  289. macclose ( int fd )
  290. {
  291.     if ( IsHandleFile ( fd ) ) {
  292.         CloseHandleFile ( fd ) ;
  293.     } else {
  294.         if ( FSClose ( fd ) ) {
  295.             return -1 ;
  296.         }
  297.         FlushVol ( (StringPtr) NULL , theDirs . dataRefNum ) ;
  298.     }
  299.     return 0 ;
  300. }
  301.  
  302.  
  303. int
  304. macread ( int fd , void * ptr , unsigned len )
  305. {
  306.     long amt = len;
  307.     
  308.     if ( IsHandleFile ( fd ) ) {
  309.  
  310.         return ReadHandleFile ( fd , ptr , amt ) ;
  311.     } else {
  312.  
  313.         short err = FSRead ( fd , & amt , ptr ) ;
  314.         if ( err == eofErr && len ) {
  315.  
  316.             return amt ;
  317.         }
  318.         if  ( itworked ( err ) ) {
  319.  
  320.             return ( amt ) ;
  321.  
  322.         } else {
  323.  
  324.             return -1 ;
  325.         }
  326.     }
  327. }
  328.  
  329.  
  330. char *
  331. macgets ( int fd , char * ptr , unsigned len )
  332. {
  333.         int idx = 0 ;
  334.         char c;
  335.  
  336.         while ( -- len > 0 ) {
  337.                 if ( macread ( fd , ptr + idx , 1 ) <= 0 )
  338.                         return NULL ;
  339.                 c = ptr[ idx++ ];
  340.                 if ( c  == '\n' || c == '\r' )
  341.                         break ;
  342.         }
  343.         ptr [ idx ] = '\0' ;
  344.         return ptr ;
  345. }
  346.  
  347.  
  348. int
  349. macwrite ( int fd , void * ptr , unsigned len )
  350. {
  351.     long amt = len ;
  352.  
  353.     if ( IsHandleFile ( fd ) ) return -1 ;
  354.     
  355.     if ( itworked( FSWrite ( fd , & amt , ptr ) ) ) return(amt) ;
  356.         else return(-1) ;
  357. }
  358.  
  359.  
  360. long
  361. macseek ( int fd , long where , short whence )
  362. {
  363.     short posMode ;
  364.     long curPos ;
  365.  
  366.     if ( IsHandleFile ( fd ) ) {
  367.         return SetHandleFilePos ( fd , whence , where ) ;
  368.     }
  369.  
  370.     switch ( whence ) {
  371.     default :
  372.         posMode = fsFromStart ;
  373.         break ;
  374.     case SEEK_CUR :
  375.         posMode = fsFromMark ;
  376.         break ;
  377.     case SEEK_END :
  378.         posMode = fsFromLEOF ;
  379.         break ;
  380.     }
  381.  
  382.     if ( itworked( SetFPos ( fd , posMode, where ) )  &&
  383.          itworked( GetFPos ( fd , &curPos )) )
  384.             return(curPos);
  385.        
  386.     return(-1);
  387. }
  388.  
  389.  
  390. static OSErr
  391. copy_file(short src_vol, long src_dir, short dst_vol, long dst_dir,
  392.           Str255 fName,
  393.           pascal OSErr (*opener)(short vRefNum, long dirID,
  394.                                  ConstStr255Param fileName,
  395.                                  char permission, short *refNum)) {
  396.     short src_ref, dst_ref;
  397.     OSErr err = (*opener)(src_vol, src_dir, fName, fsRdPerm, &src_ref);
  398.     if (err == noErr) {
  399.         err = (*opener)(dst_vol, dst_dir, fName, fsWrPerm, &dst_ref);
  400.         if (err == noErr) {
  401.  
  402.             long file_len;
  403.             err = GetEOF(src_ref, &file_len);
  404.             if (err == noErr) {
  405.                 Handle buf;
  406.                 long count = MaxBlock();
  407.                 if (count > file_len)
  408.                     count = file_len;
  409.  
  410.                 buf = NewHandle(count);
  411.                 err = MemError();
  412.                 if (err == noErr) {
  413.  
  414.                     while (count > 0) {
  415.                         OSErr rd_err = FSRead(src_ref, &count, *buf);
  416.                         err = FSWrite(dst_ref, &count, *buf);
  417.                         if (err == noErr)
  418.                             err = rd_err;
  419.                         file_len -= count;
  420.                     }
  421.                     if (file_len == 0)
  422.                         err = noErr;
  423.  
  424.                     DisposHandle(buf);
  425.  
  426.                 }
  427.             }
  428.             FSClose(dst_ref);
  429.         }
  430.         FSClose(src_ref);
  431.     }
  432.  
  433.     return err;
  434. }
  435.  
  436. static void
  437. force_hdelete(short vol, long dir, Str255 fName) {
  438.     HRstFLock(vol, dir, fName);
  439.     HDelete  (vol, dir, fName);
  440. }
  441.  
  442. void
  443. finder_file_request(void) {
  444.     short finder_msg, file_count;
  445.     CountAppFiles(&finder_msg, &file_count);
  446.     if (finder_msg == appOpen && file_count == 1) {
  447.         OSErr    err;
  448.         AppFile src;
  449.         short    src_vol;
  450.         long    src_dir, nul = 0;
  451.         GetAppFiles(1, &src);
  452.         err = GetWDInfo(src.vRefNum, &src_vol, &src_dir, &nul);
  453.         if (err == noErr && src.fType == SAVE_TYPE) {
  454.  
  455.             if ( src_vol != theDirs.dataRefNum ||
  456.                  src_dir != theDirs.dataDirID &&
  457.                  CatMove(src_vol, src_dir, src.fName,
  458.                          theDirs.dataDirID, "\p:") != noErr) {
  459.  
  460.                 HCreate(theDirs.dataRefNum, theDirs.dataDirID, src.fName,
  461.                         MAC_CREATOR, SAVE_TYPE);
  462.                 err = copy_file(src_vol, src_dir, theDirs.dataRefNum,
  463.                                 theDirs.dataDirID, src.fName, &HOpen); /* HOpenDF is only there under 7.0 */
  464.                 if (err == noErr)
  465.                     err = copy_file(src_vol, src_dir, theDirs.dataRefNum,
  466.                                     theDirs.dataDirID, src.fName, &HOpenRF);
  467.                 if (err == noErr)
  468.                     force_hdelete(src_vol, src_dir, src.fName);
  469.                 else
  470.                     HDelete(theDirs.dataRefNum, theDirs.dataDirID, src.fName);
  471.             }
  472.  
  473.             if (err == noErr) {
  474.                 short ref = HOpenResFile(theDirs.dataRefNum, theDirs.dataDirID,
  475.                                          src.fName, fsRdPerm);
  476.                 if (ref != -1) {
  477.                     Handle name = Get1Resource('STR ', PLAYER_NAME_RES_ID);
  478.                     if (name) {
  479.  
  480.                         Str255 save_f_p;
  481.                         P2C(*(StringHandle)name, plname);
  482.                         set_savefile_name();
  483.                         C2P(SAVEF, save_f_p);
  484.                         force_hdelete(theDirs.dataRefNum, theDirs.dataDirID,
  485.                                       save_f_p);
  486.                         if (HRename(theDirs.dataRefNum, theDirs.dataDirID,
  487.                                     src.fName, save_f_p) == noErr)
  488.                             ClrAppFiles(1);
  489.  
  490.                     }
  491.                     CloseResFile(ref);
  492.                 }
  493.             }
  494.         }
  495.     }
  496. }
  497.